package com.stylefeng.guns.modular.push_msg.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.notnoop.apns.APNS;
import com.notnoop.apns.ApnsService;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.modular.apple.vo.Paging;
import com.stylefeng.guns.modular.device_token.dao.DeviceTokenMapper;
import com.stylefeng.guns.modular.push_msg.dto.PushNewMsgDTO;
import com.stylefeng.guns.modular.push_msg.model.BundleDO;
import com.stylefeng.guns.modular.push_msg.model.DeviceTokenDO;
import com.stylefeng.guns.modular.push_msg.model.PushMsg;
import com.stylefeng.guns.modular.push_msg.dao.PushMsgMapper;
import com.stylefeng.guns.modular.push_msg.model.PushMsgDO;
import com.stylefeng.guns.modular.push_msg.service.IPushMsgService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.modular.user_buy_device.bo.UserBuyDeviceBO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;

/**
 * <p>
 * 消息推送信息表 服务实现类
 * </p>
 *
 * @author GodRui
 * @since 2020-08-04
 */
@Service
public class PushMsgServiceImpl extends ServiceImpl<PushMsgMapper, PushMsg> implements IPushMsgService {

    @Resource
    private DeviceTokenMapper deviceTokenMapper;

    @Value("${push-info.certificate-path}")
    private String certificatePath;

    @Override
    public Object listMsg(Integer page, Integer limit) {
        int start = (page>0?page-1:page) * limit;
        Paging<PushMsgDO> paging = new Paging<>();
        paging.setItems(this.baseMapper.findAllMsg((ShiroKit.isAdmin()?null:ShiroKit.getUser().getId()),start,limit));
        EntityWrapper<PushMsg> wrapper = new EntityWrapper<>();
        if (!ShiroKit.isAdmin()){
            wrapper.eq("user_id",ShiroKit.getUser().getId());
        }
        paging.setTotal(this.baseMapper.selectCount(wrapper).longValue());
        return paging;
    }

    @Override
    @Transactional
    public void pushMsg(PushNewMsgDTO pushMsgDTO) {
        long msgId = this.addPushMsg(pushMsgDTO);
        if(msgId > 0){
            //1、创建推送内容
            String payload = APNS.newPayload()
                    .alertTitle(pushMsgDTO.getTitle())
                    .alertBody(pushMsgDTO.getContent())
                    .customFields(getCustomForm(pushMsgDTO.getCustom()))
                    .badge(1)
                    .build();

            //2、根据app_code获取到bundle_id，account
            List<BundleDO> bundleDOList = deviceTokenMapper.findBundleOfAppCode(pushMsgDTO.getAppCode());

            //3、根据bundle_Id获取每个的device_token集合
            bundleDOList.forEach(a->{
                List<DeviceTokenDO> deviceTokenDOList = deviceTokenMapper.findDeviceTokenOfBundle(a.getBundleId());
                //获取DeviceToken列表
                ArrayList<String> deviceIds = new ArrayList<>();
                deviceTokenDOList.forEach(dt->{
                    deviceIds.add(dt.getDeviceToken());
                });

                //4、根据app_code 和 account在证书的目录中获取到证书文件流
                //证书目录结构： ../data/html/data/{app_code}/{acount}/证书名字.p12
                String filePath = certificatePath +pushMsgDTO.getAppCode()+"/"+a.getAppleAccount()+"/production_"+a.getBundleId()+".p12";
                InputStream stream;
                try {
                    //根据苹果证书的目录地址，读取文件流
                    stream = new FileInputStream(filePath);
                    //5、传递证书文件流、推送内容、deviceToken集合进行推送
                    push(stream,payload,deviceIds);
                    this.baseMapper.updateMsgStatus(1,msgId);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new GunsException(BizExceptionEnum.PUSH_MSG_FAIL);
                }
            });
        }else{
            throw new GunsException(BizExceptionEnum.PUSH_MSG_FAIL);
        }
    }

    @Override
    public long addPushMsg(PushNewMsgDTO pushMsgDTO) {
        if(StringUtils.isEmpty(pushMsgDTO.getTitle())
                || StringUtils.isEmpty(pushMsgDTO.getContent())
                || StringUtils.isEmpty(pushMsgDTO.getAppCode())){
            throw new GunsException(BizExceptionEnum.PUSH_MSG_PARAM_ERROR);
        }

        if (pushMsgDTO.getTitle().length() > 30){
            throw new GunsException(BizExceptionEnum.PUSH_MSG_TITLE_SIZE_TOO_LONG);
        }
        if (pushMsgDTO.getContent().length() > 100){
            throw new GunsException(BizExceptionEnum.PUSH_MSG_CONTENT_SIZE_TOO_LONG);
        }
        pushMsgDTO.setUserId(ShiroKit.getUser().getId());
        pushMsgDTO.setCreateTime(new Date());

        this.baseMapper.addNewMsg(pushMsgDTO);

        return pushMsgDTO.getId();
    }

    /**
     * 调用推送方法，进行消息推送
     * @param stream
     * @param payload
     * @param deviceIds
     */
    public void push(InputStream stream,String payload,ArrayList<String> deviceIds){
        ApnsService service = APNS.newService()
                .withCert(stream, "asf123")
                .withProductionDestination()
                //.withSandboxDestination()
                .build();
        //推送消息
        service.push(deviceIds, payload);
    }

    private Map<String,Object> getCustomForm(String customStr){
        Map<String,Object> extra = new HashMap<>();
        if (!customStr.contains(",")){
            if (customStr.contains(":")){
                int index = customStr.indexOf(":");
                extra.put(customStr.substring(0,index),customStr.substring(index+1));
            }
        }else{
            String[] customs = customStr.split(",");
            int len = customs.length;
            for (int i = 0;i < len;i++){
                if (customs[i].contains(":")){
                    int index = customs[i].indexOf(":");
                    extra.put(customs[i].substring(0,index),customs[i].substring(index+1));
                }
            }
        }

        return extra;
    }

}
